home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / dejagnu.lha / dejagnu-1.0.1 / expect / exp_select.c < prev    next >
C/C++ Source or Header  |  1993-03-29  |  5KB  |  217 lines

  1. /* exp_select.c - select() interface for Expect
  2.  
  3. Written by: Don Libes, NIST, 2/6/90
  4.  
  5. Design and implementation of this program was paid for by U.S. tax
  6. dollars.  Therefore it is public domain.  However, the author and NIST
  7. would appreciate credit if this program or parts of it are used.
  8.  
  9. */
  10.  
  11. #include "exp_conf.h"
  12. #include <stdio.h>
  13. #include <errno.h>
  14. #include <sys/types.h>
  15. #include <sys/time.h>
  16.  
  17. #ifdef HAVE_PTYTRAP
  18. #  include <sys/ptyio.h>
  19. #endif
  20.  
  21. #ifdef HAVE_UNISTD_H
  22. #  include <unistd.h>
  23. #endif
  24. #ifdef _AIX
  25. /* AIX has some unusual definition of FD_SET */
  26. #include <sys/select.h>
  27. #endif
  28.  
  29. #include "tcl.h"
  30. #include "exp_global.h"
  31. #include "exp_command.h"    /* for struct f defs */
  32. #include "exp_event.h"
  33.  
  34. #ifdef HAVE_SYSCONF_H
  35. #include <sys/sysconfig.h>
  36. #endif
  37.  
  38. #ifndef FD_SET
  39. #define FD_SET(fd,fdset)    (fdset)->fds_bits[0] |= (1<<(fd))
  40. #define FD_CLR(fd,fdset)    (fdset)->fds_bits[0] &= ~(1<<(fd))
  41. #define FD_ZERO(fdset)        (fdset)->fds_bits[0] = 0
  42. #define FD_ISSET(fd,fdset)    (((fdset)->fds_bits[0]) & (1<<(fd)))
  43. #ifndef AUX2
  44. typedef struct fd_set {
  45.     long fds_bits[1];
  46.     /* any implementation so pathetic as to not define FD_SET will just */
  47.     /* have to suffer with only 32 bits worth of fds */
  48. } fd_set;
  49. #endif /* AUX2 */
  50. #endif
  51.  
  52. static struct timeval zerotime = {0, 0};
  53. static struct timeval anytime = {0, 0};    /* can be changed by user */
  54.  
  55. static int maxfds;
  56.  
  57. /*ARGSUSED*/
  58. void
  59. exp_event_disarm(fd)
  60. int fd;
  61. {
  62. }
  63.  
  64. /* returns status, one of EOF, TIMEOUT, ERROR or DATA */
  65. int
  66. exp_get_next_event(interp,masters, n,master_out,timeout,key)
  67. Tcl_Interp *interp;
  68. int *masters;
  69. int n;            /* # of masters */
  70. int *master_out;    /* 1st event master, not set if none */
  71. int timeout;        /* seconds */
  72. int key;
  73. {
  74.     static rr = 0;    /* round robin ptr */
  75.  
  76.     int i;    /* index into in-array */
  77.     struct timeval *t;
  78.  
  79.     fd_set rdrs;
  80.     fd_set excep;
  81. #define EXCEP &excep
  82.  
  83. #if 0
  84. #ifdef HAVE_PTYTRAP
  85.     fd_set excep;
  86. #define EXCEP &excep
  87. #else
  88. #define EXCEP (fd_set *)0
  89. #endif
  90. #endif
  91.  
  92.     for (i=0;i<n;i++) {
  93.         struct f *f;
  94.         int m;
  95.  
  96.         rr++;
  97.         if (rr >= n) rr = 0;
  98.  
  99.         m = masters[rr];
  100.         f = fs + m;
  101.  
  102.         if (f->key != key) {
  103.             f->key = key;
  104.             f->force_read = FALSE;
  105.             *master_out = m;
  106.             return(EXP_DATA_OLD);
  107.         } else if ((!f->force_read) && (f->size != 0)) {
  108.             *master_out = m;
  109.             return(EXP_DATA_OLD);
  110.         }
  111.     }
  112.  
  113.     if (timeout >= 0) {
  114.         t = &anytime;
  115.         t->tv_sec = timeout;
  116.     } else {
  117.         t = NULL;
  118.     }
  119.  
  120.  restart:
  121.     FD_ZERO(&rdrs);
  122.     FD_ZERO(&excep);
  123. #if 0
  124. #ifdef HAVE_PTYTRAP
  125.     FD_ZERO(&excep);
  126. #endif
  127. #endif
  128.     for (i = 0;i < n;i++) {
  129.         FD_SET(masters[i],&rdrs);
  130.         FD_SET(masters[i],&excep);
  131. #if 0
  132. #ifdef HAVE_PTYTRAP
  133.         FD_SET(masters[i],&excep);
  134. #endif
  135. #endif
  136.     }
  137.  
  138.     if (-1 == select(maxfds,&rdrs,(fd_set *)0,EXCEP,t)) {
  139.         /* window refreshes trigger EINTR, ignore */
  140.         if (errno == EINTR) goto restart;
  141.         else if (errno == EBADF) {
  142.             /* someone is rotten */
  143.             for (i=0;i<n;i++) {
  144.             fd_set suspect;
  145.             FD_ZERO(&suspect);
  146.             FD_SET(masters[i],&suspect);
  147.             if (-1 == select(maxfds,&suspect,
  148.                         (fd_set *)0,(fd_set *)0,&zerotime)) {
  149.                 exp_error(interp,"invalid spawn_id (%d)\r",masters[i]);
  150.                 return(EXP_TCLERROR);
  151.             }
  152.            }
  153.             } else {
  154.             /* not prepared to handle anything else */
  155.             exp_error(interp,"select: %s\r",sys_errlist[errno]);
  156.             return(EXP_TCLERROR);
  157.         }
  158.     }
  159.  
  160.     for (i=0;i<n;i++) {
  161.         rr++;
  162.         if (rr >= n) rr = 0;    /* ">" catches previous readys that */
  163.                 /* used more fds then we're using now */
  164.  
  165.         if (FD_ISSET(masters[rr],&rdrs)) {
  166.             *master_out = masters[rr];
  167.             return(EXP_DATA_NEW);
  168. /*#ifdef HAVE_PTYTRAP*/
  169.         } else if (FD_ISSET(masters[rr], &excep)) {
  170. #ifndef HAVE_PTYTRAP
  171.             *master_out = masters[rr];
  172.             return(EXP_EOF);
  173. #else
  174.             struct request_info ioctl_info;
  175.             if (ioctl(masters[rr],TIOCREQCHECK,&ioctl_info) < 0) {
  176.                 exp_debuglog("ioctl error on TIOCREQCHECK: %d", errno);
  177.                 break;
  178.             }
  179.             if (ioctl_info.request == TIOCCLOSE) {
  180.                 /* eof */
  181.                 *master_out = masters[rr];
  182.                 return(EXP_EOF);
  183.             }
  184.             if (ioctl(masters[rr], TIOCREQSET, &ioctl_info) < 0)
  185.                 exp_debuglog("ioctl error on TIOCREQSET after ioctl or open on slave: %d", errno);
  186.             /* presumably, we trapped an open here */
  187.             goto restart;
  188. #endif /* HAVE_PTYTRAP */
  189.         }
  190.     }
  191.     return(EXP_TIMEOUT);
  192. }
  193.  
  194. void
  195. exp_usleep(usec)
  196. long usec;        /* microseconds */
  197. {
  198.     struct timeval t;
  199.  
  200.     t.tv_sec = usec/1000000L;
  201.     t.tv_usec = usec%1000000L;
  202.     (void) select(1, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
  203. }
  204.  
  205. /* set things up for later calls to event handler */
  206. void
  207. exp_init_event()
  208. {
  209. #ifdef HAVE_SYSCONF
  210.     maxfds = sysconf(_SC_OPEN_MAX);
  211. #else
  212.     maxfds = getdtablesize();
  213. #endif
  214.  
  215.     exp_event_exit = 0;
  216. }
  217.